﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NAnt.Core.Types;
using NAnt.Core.Attributes;
using System.IO;
using NAnt.Core;
using NAnt.SVN.Process;

namespace NAnt.SVN.Tasks
{
    /// <summary>
    /// Special intermediate task to run with filesets.
    /// $Id$
    /// </summary>
    public abstract class SVNFilesetTask : SVNTask
    {
        #region Private Fields

        private FileSet files;
        private int countSucces = 0;
        private int countFailed = 0;

        #endregion

        #region Public fields

        /// <summary>
        /// The fileset to use
        /// </summary>
        [BuildElement("fileset", Required = false)]
        public virtual FileSet Files
        {
            get { return files; }
            set { files = value; }
        }

        #endregion

        /// <summary>
        /// This callback function is called on every run of the fileset
        /// </summary>
        /// <param name="e"></param>
        public abstract void OnHasRunFile(ProcessRunnerData e);

        /// <summary>
        /// Increment the statistics
        /// </summary>
        /// <param name="e"></param>
        public void IncrementStatistics(ProcessRunnerData e)
        {
            if (e.ExitCode == 0)
                countSucces++;
            else
            {
                countFailed++;
                Log(Level.Verbose, string.Format(getString("SVN0307"), e.Command, e.Options));
            }
        }

        /// <summary>
        /// Execute the fileset
        /// </summary>
        protected override void ExecuteTask()
        {
            InitializeSVNTask();
            // ensure base directory is set, even if fileset was not initialized
            // from XML
            if (Files.BaseDirectory == null)
            {
                Files.BaseDirectory = new DirectoryInfo(Project.BaseDirectory);
            }
            //Instantiate a process
            if(Runner == null) Runner = new ProcessRunner();
            Runner.OnHasRun += new AbstractProcessRunner.OnHasRunEventHandler(OnHasRun);
            Runner.OnHasRun += new AbstractProcessRunner.OnHasRunEventHandler(OnHasRunFile);
            Runner.OnHasRun += new AbstractProcessRunner.OnHasRunEventHandler(IncrementStatistics);

            //Loop all the files
            foreach(string file in Files.FileNames)
            {
                try
                {
                    Runner.Execute(this, string.Format(FormattedOptions, quote(file)));
                }
                catch (Exception e)
                {
                    throw new BuildException(
                        string.Format(getString("SVN0306"), file, e.Message), 
                        Location, e);
                }
            }
            //Log final statistics
            Log(Level.Info, string.Format(getString("SVN0107"), countFailed + countSucces));
            Log(Level.Info, string.Format(getString("SVN0108"), countSucces, countFailed));
        }
    }
}
